package com.my.lambda;


import org.junit.Test;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.function.*;

/**
 * 1. Consumer<T>:消费型接口
 * void accept(T t);
 * <p>
 * 2. Supplier<T> :供给型接口
 * T  get();
 * <p>
 * 3. Function<T,R>: 函数型接口
 * R  apply(T t);
 * <p>
 * 4. Predicate<T>: 断言型接口
 * boolean test(T t)
 * <p>
 * //UnaryOperator<T>         T      T
 * //BinaryOperator<T>        T,U    T
 * //BiFunction<T, U, R>      T,U     R
 * //BiPredicate<T,U>         T,U     boolean
 * //BiConsumer<T,U>          T,U     void
 */
/*函数型接口编写*/
public class LambdaTest {

    @Test
    public void Test2() {
        Supplier<String> supplier = () -> "123";
        System.out.println(supplier.get());

        Function<String, String> function = (x) -> x + "123";
        System.out.println(function.apply("23"));

        BiFunction<String, Integer, String> biFunction = (x, y) -> x + y;
        System.out.println(biFunction.apply("12", 2));
    }

    //策略模式
    @FunctionalInterface
    interface MyFun {
        Integer count(Integer a, Integer b);
    }

    public Integer operation(Integer a, Integer b, MyFun myFun) {
        return myFun.count(a, b);
    }

    @Test
    public void Test3() {
        Integer result = operation(1, 2, (x, y) -> x + y);
        System.out.println(result);


        repeat(() -> System.out.println("main begin 1"));
        repeat(() -> System.out.println("main begin 2"));
        repeat(() -> System.out.println("main begin 3"));


        // 这是将代码块传递到sort
        String[] planets = new String[]{"Mer1", "Ve33ee4n", "E399999AR", "MA2RS"};
        System.out.println(Arrays.toString(planets));
        System.out.println("Sorted in dictionary order:");
        Arrays.sort(planets);
        System.out.println(Arrays.toString(planets));
        System.out.println("sorted by length:");
        Arrays.sort(planets, (first, second) -> first.length() - second.length());
        System.out.println(Arrays.toString(planets));
        //这是将代码块传递到repeat 方法的action对象
        repeat(10, () -> System.out.println("hello world"));
    }

    static void repeat(Iconsumer iconsumer) {
        iconsumer.accept();
    }

    interface Iconsumer {
        public void accept();
    }

    static void repeat(int n, Runnable action) {
        for (int i = 0; i <= n; i++) {
            action.run();
        }
    }

    /**
     * 方法引用:若lambda 体中的内容已经有方法实现了，我们可以使用"方法引用"
     * 三种语法：
     * 对象::实例方法名
     * 类::静态方法名
     * 类::实例方法名
     * <p>
     * 构造器引用 Class::new
     * <p>
     * 数组引用  type：：new
     */
    @Test
    public void Test4() {
        //对象::实例方法名
        Consumer<String> consumer = (x) -> System.out.println(x);
        PrintStream println = System.out;
        Consumer<String> consumer1 = println::println;
        Consumer<String> consumer2 = System.out::println;
        consumer2.accept("xx");

        HashMap map = new HashMap();
        map.put(100, "三个人");
        map.put(110, "四个人");
        map.put(115, "五个人");
        map.put(120, "一群人");
        // 这个consumer 可以理解为一个函数，函数内容就是后面的lambda 表达式
        Consumer<Map> consumermap = x -> {
            x.forEach((k, v) -> System.out.println("key:" + k + "value:" + v));
        };
        consumermap.accept(map);

        HashMap mapMonkey = new HashMap();
        mapMonkey.put(100, "三只猴");
        mapMonkey.put(110, "四只猴");
        mapMonkey.put(115, "五只猴");
        mapMonkey.put(120, "一群猴");
        // BiConsumer 接受接受两个参数，一个是map，一个是 consumer
        BiConsumer<Map, Consumer> biConsumer = (map1, consumer22) ->
        {
            consumer22.accept(map1);
        };
        biConsumer.accept(mapMonkey, consumer);

        //类::静态方法名
        Comparator<Integer> comparator3 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };
        Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
        Comparator<Integer> comparator2 = Integer::compare;
        //类::实例方法名
        BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);
        BiPredicate<String, String> biPredicate2 = String::equals; //ClassName::method 必须x.equals(y)
        //构造器引用
        Supplier<String> stringSupplier = () -> new String();
        Supplier<String> stringSupplier2 = String::new;//自动匹配有参数无参 具体取决于使用的函数类型（函数有几个参数）
        //数组引用
        Function<Integer, String[]> function = (x) -> new String[x];
        Function<Integer, String[]> function1 = String[]::new;
//        Function<String,String[]> function2 = String[]::new; 错误的
    }
}
